package com.cw.controller;


import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cw.common.api.ResultObject;
import com.cw.common.constant.RedisConstant;
import com.cw.config.JwtConfig;
import com.cw.constant.Constants;
import com.cw.dto.SysUserDTO;
import com.cw.dto.SystemLogCondition;
import com.cw.entity.SysRole;
import com.cw.entity.SysUser;
import com.cw.entity.SysUserRole;
import com.cw.service.ISysUserRoleService;
import com.cw.service.ISysUserService;
import com.cw.util.HttpUtil;
import com.cw.util.RedisUtils;
import com.cw.util.UUIDUtil;
import com.cw.websocket.SocketHandler;
import com.github.pagehelper.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author smq
 * @since 2021-04-28
 */
@Api(tags = {"用户表"})
@RestController
@RequestMapping("/sys-user")
@Slf4j
public class SysUserController {

    @Autowired
    private ISysUserService targetService;

    @Resource
    private JwtConfig jwtConfig;

    @Autowired
    private ISysUserRoleService iSysUserRoleService;

    @Autowired
    private SocketHandler socketHandler;

    @Autowired
    private RedisUtils redisUtils;


    /**
     * 分页查询所有用户信息
     */
    @ApiOperation("分页展示查询")
    @PostMapping("/totalSysuser")
    public ResultObject sysUserSelectList(@RequestBody SystemLogCondition condition) {
        return ResultObject.successReturn(targetService.sysUserSelectList(condition));
    }

    @ApiOperation("登录")
    @PostMapping("/login")
    public ResultObject login(@RequestBody SysUser sysUser) {
        String password = SecureUtil.md5(sysUser.getPassword());
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(SysUser::getUsername,
                SysUser::getRealname,
                SysUser::getUserId,
                SysUser::getLoginFirst,
                SysUser::getYard,
                SysUser::getEnable);
        lambdaQueryWrapper.eq(SysUser::getUsername, sysUser.getUsername());
        lambdaQueryWrapper.eq(SysUser::getPassword, password);
        lambdaQueryWrapper.eq(SysUser::getDelFlag, "0");
        List<SysUser> list = targetService.list(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return ResultObject.errorReturn("用户名或者密码输入错误!!");
        }
        SysUser userBo = list.get(0);
        Map<String, Object> map = new HashMap<>(4);
        map.put("userName", userBo.getUsername());
        map.put("password", password);
        map.put("yard", userBo.getYard());

        String enable = userBo.getEnable();
        if (StringUtil.isNotEmpty(enable) && "1".equals(enable)) {
            return ResultObject.errorReturn("当前账号被禁用");
        }
        String token = jwtConfig.getToken(map);
        if (!StringUtils.isEmpty(token)) {
            map.put("token", token);
        }

        //判断是否第一次登录,如果是就要前端弹起强制修改密码窗口
        int loginFirst = 0;
        if ("1".equals(userBo.getLoginFirst())) {
            loginFirst = 1;
        }
        map.put("loginFirst", loginFirst);
        map.put("SysUserInfo", userBo);
        map.remove("password");

        return ResultObject.successReturn(map);
    }

    @ApiOperation("单点登录")
    @RequestMapping(value = "/login2")
    public void login2(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Map<String, String[]> parameterMap = req.getParameterMap();
        log.info("parameterMap -> {}", parameterMap);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //指定接口发送post请求
        HttpPost httpPost = new HttpPost("http://portalembed-ops-ewell-prodsfey.sfey.com:31351/api/userByPortal");
        String token = parameterMap.get("token")[0];
        String appId = parameterMap.get("appId")[0];
        log.info("appId -> {}", appId);
        //增加header
        httpPost.addHeader("Content-Type", "application/json");
        httpPost.addHeader("token", token);
        httpPost.addHeader("appId", appId);
        try {
            CloseableHttpResponse response = httpClient.execute(httpPost);
            log.info("execute success !");
            log.info("response -> {}", response);
            HttpEntity entity = response.getEntity();
            String s = EntityUtils.toString(entity);
            log.info("HttpEntity -> {}", entity);
            log.info("HttpEntity->S -> {}", s);
            Map map = JSONObject.parseObject(s, Map.class);
            log.info("content -> {}", s);
            log.info("map -> {}", map);
            String status = map.get("status").toString();
            log.info("status -> {}", status);
            String staffCode = (String) map.get("staffCode");
            log.info("staffCode -> {}", staffCode);
            if (!"0".equals(status)) {
                log.info("redirect if ! ");
                resp.sendRedirect("http://172.16.1.38:10088/trilogin?staffCode=error");
                return;
            }
            // 删除ewell和cwtoken 的绑定关系
            if (redisUtils.get(RedisConstant.getEwellToken(staffCode)) != null && redisUtils.get(RedisConstant.getCwToken(
                    redisUtils.get(RedisConstant.getEwellToken(staffCode)).toString())) != null) {
                redisUtils.del(RedisConstant.getCwToken(redisUtils.get(RedisConstant.getEwellToken(staffCode))
                        .toString()));
            }
            redisUtils.set(RedisConstant.getEwellToken(staffCode), token, 60 * 15);
            log.info("redirect success ! ");
            resp.sendRedirect("http://172.16.1.38:10088/trilogin?staffCode=" + staffCode);

        } catch (IOException e) {
            e.printStackTrace();
            resp.sendRedirect("http://172.16.1.38:10088/trilogin?staffCode=error");
        }
    }

    @ApiOperation("获取登录信息")
    @GetMapping(value = "/getLoginInfo")
    public ResultObject getLoginInfo(@RequestParam String staffCode) {
        // 拿对应的绑定关系
        if (redisUtils.get(RedisConstant.getEwellToken(staffCode)) == null) {
            return ResultObject.errorReturn("登录token不存在");
        }
        if (redisUtils.get(RedisConstant.getCwToken(redisUtils.get(RedisConstant.getEwellToken(staffCode))
                .toString())) != null) {
            return ResultObject.errorReturn("登录token失效");
        }
        Map<String, Object> map = new HashMap<>(4);
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(SysUser::getUsername, SysUser::getUserId);
        lambdaQueryWrapper.eq(SysUser::getUsername, staffCode);
        lambdaQueryWrapper.eq(SysUser::getDelFlag, "0");
        List<SysUser> list1 = targetService.list(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(list1)) {
            return ResultObject.errorReturn("用户不存在");
        } else {
            SysUser user = list1.get(0);
            map.put("userName", user.getUsername());
            map.put("passWord", user.getPassword());
            String newToken = jwtConfig.getToken(map);
            map.put("SysUserInfo", user);
            map.put("token", newToken);
            map.remove("passWord");
            redisUtils.set(RedisConstant.getCwToken(redisUtils.get(RedisConstant.getEwellToken(staffCode)).toString()),
                    newToken,
                    60 * 60 * 7);
        }
        return ResultObject.successReturn(map);
    }

    @ApiOperation("退出登录")
    @GetMapping(value = "/loginOut")
    public ResultObject loginOut(@RequestParam String staffCode) {
        // 清除redis缓存--绑定
        if (redisUtils.get(RedisConstant.getEwellToken(staffCode)) != null) {
            redisUtils.del(RedisConstant.getCwToken(redisUtils.get(RedisConstant.getEwellToken(staffCode)).toString()));
        }
        // 清除redis缓存 -- 工号+ewell Token
        redisUtils.del(RedisConstant.getEwellToken(staffCode).toString());
        return ResultObject.success("退出登录");
    }


    /**
     * 修改用户信息
     *
     * @param sysUser
     * @return
     */
    @ApiOperation("编辑")
    @PostMapping("/updateSysUser")
    public ResultObject updateSysUser(@RequestBody SysUser sysUser) {

        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("USERNAME", sysUser.getUsername());
        if (!CollectionUtils.isEmpty(targetService.list(queryWrapper))) {
            //主键对比,是否是当前的用户
            SysUser oldSysUser = targetService.getById(sysUser.getUserId());
            String oldUserId = oldSysUser.getUserId();
            if (!oldUserId.equals(sysUser.getUserId())) {
                return ResultObject.failed("此用户已经存在，请重新输入");
            }
        }
        String password = sysUser.getNewPassword();
        //强度校验
        String passwordPattern = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
        if (!password.matches(passwordPattern)) {
            return ResultObject.failed("密码强度不足，必须包含至少一个大写字母、一个小写字母、一个数字和一个特殊符号，且长度至少为8个字符");
        }
        if (com.cw.util.StringUtil.isNotEmpty(password)) {
            String passwd = SecureUtil.md5(password);
            sysUser.setPassword(passwd);
        } else {
            sysUser.setPassword(null);
        }
        sysUser.setUpdateTime(LocalDateTime.now());
        //编辑对象
        if (targetService.updateById(sysUser)) {
            //先删除之前的数据在插入
            iSysUserRoleService.deleteRoleByUser(sysUser.getUserId());

            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setId(UUIDUtil.uuid());
            sysUserRole.setUserId(sysUser.getUserId());
            sysUserRole.setRoleId(sysUser.getRoleCode());
            sysUserRole.setCreateBy(sysUser.getUsername());
            sysUserRole.setDeleteFlag(sysUser.getDelFlag());
            iSysUserRoleService.save(sysUserRole);
            return ResultObject.successReturn("修改成功");
        } else {
            return ResultObject.errorReturn("修改失败");
        }
    }

    @ApiOperation("详情")
    @PostMapping("/getBySysUser")
    public ResultObject getBySysUser(@RequestParam String userId) {
        SysUser byId = targetService.getById(userId);
        byId.setPassword(null);
        SysRole sysUserRole = iSysUserRoleService.getRoleByUserId(userId);
        if (sysUserRole != null) {
            byId.setRoleName(sysUserRole.getRoleName());
        }
        return ResultObject.successReturn(byId);
    }

    /**
     * 根据用户id删除用户
     *
     * @param id
     * @return
     */
    @ApiOperation("删除")
    @PostMapping(value = "/deleteById/{id}")
    public ResultObject deleteById(@PathVariable String id) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(id);
        sysUser.setDelFlag("1");
        targetService.updateById(sysUser);
        return ResultObject.successReturn("删除成功");
    }

    /**
     * 新增新的用户
     *
     * @param sysUser
     * @return
     */
    @ApiOperation("添加用户")
    @PostMapping(value = "/addSysUser")
    public ResultObject addSysUser(@RequestBody SysUser sysUser) {
        String userName = HttpUtil.getRequestHeaderInfo(Constants.USER_NAME);
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("USERNAME", sysUser.getUsername());
        queryWrapper.eq("DEL_FLAG", "0");
        //重复userName
        if (!CollectionUtils.isEmpty(targetService.list(queryWrapper))) {
            return ResultObject.failed("此用户已经存在，请重新输入");
        }
        String password = sysUser.getPassword();
        String passwordPattern = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
        if (!password.matches(passwordPattern)) {
            return ResultObject.failed("密码强度不足，必须包含至少一个大写字母、一个小写字母、一个数字和一个特殊符号，且长度至少为8个字符");
        }
        String passwd = SecureUtil.md5(password);
        sysUser.setPassword(passwd);
        sysUser.setUpdateTime(LocalDateTime.now());
        if (targetService.save(sysUser)) {
            //插入新的数据
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(sysUser.getUserId());
            sysUserRole.setRoleId(sysUser.getRoleCode());
            sysUserRole.setCreateBy(sysUser.getUsername());
            sysUserRole.setCreateBy(userName);
            sysUserRole.setDeleteFlag("0");
            iSysUserRoleService.save(sysUserRole);
            return ResultObject.successReturn("增加成功");
        } else {
            return ResultObject.errorReturn("增加失败");
        }

    }

    @ApiOperation("编辑用户")
    @PutMapping("/editSysUser")
    public ResultObject editSysUser(@RequestBody SysUser sysUser) {
        String password = sysUser.getPassword();
        String passwordPattern = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
        if (!password.matches(passwordPattern)) {
            return ResultObject.failed("密码强度不足，必须包含至少一个大写字母、一个小写字母、一个数字和一个特殊符号，且长度至少为8个字符");
        }
        return ResultObject.successReturn(targetService.updateById(sysUser));
    }

    @ApiOperation("更改密码")
    @PutMapping("/updatePassWord")
    public ResultObject updatePassWord(@RequestBody SysUserDTO sysUserDTO) {
        String password = sysUserDTO.getNewPassword();
        //查询数据库密码
        String userId = sysUserDTO.getUserId();
        String passwordPattern = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
        if (!password.matches(passwordPattern)) {
            return ResultObject.failed("密码强度不足，必须包含至少一个大写字母、一个小写字母、一个数字和一个特殊符号，且长度至少为8个字符");
        }
        //修改
        String inputNewPassword = SecureUtil.md5(password);
        SysUser sysUserEdit = new SysUser();
        sysUserEdit.setUserId(userId);
        sysUserEdit.setPassword(inputNewPassword);
        return ResultObject.successReturn(targetService.updateById(sysUserEdit));
    }

    @ApiOperation("第一次登录更改密码")
    @PutMapping("/firstLoginEditPassWord")
    public ResultObject firstLoginEditPassWord(@RequestBody SysUserDTO sysUserDTO) {
        String password = sysUserDTO.getNewPassword();
        String userId = sysUserDTO.getUserId();
        String passwordPattern = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
        if (!password.matches(passwordPattern)) {
            return ResultObject.failed("密码强度不足，必须包含至少一个大写字母、一个小写字母、一个数字和一个特殊符号，且长度至少为8个字符");
        }
         // 加密
        String newPassword = SecureUtil.md5(password);
        SysUser editSysUser = new SysUser();
        editSysUser.setUserId(userId);
        editSysUser.setLoginFirst("1");
        editSysUser.setPassword(newPassword);
        return ResultObject.successReturn(targetService.updateById(editSysUser));
    }


    @ApiOperation("重置密码")
    @GetMapping("/restartPassword")
    public ResultObject restartPassword(@RequestParam String userId) {
        //初始密码
        String password = SecureUtil.md5("Cwgl@123456");
        //修改密码
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setPassword(password);
        return ResultObject.successReturn(targetService.updateById(sysUser));
    }
}